

#include "bsp_uart_2.h"
#include "utility.h"
#include "debug.h"

#include "FreeRTOS.h"
#include "stream_buffer.h"
#include "event_groups.h"

#include <assert.h>
#include "simple_protocol.h"

#define UART_DMA_BUF_SIZE		64
#define UART_DMA_TX_BUF_NUM		2

#define UART_DMA_F_IDLE			1
#define UART_DMA_F_FREE			2

typedef struct _uart_dma_buf{
	uint8_t buf[UART_DMA_BUF_SIZE];
	uint8_t len;
}uart_dma_buf_t;

static StreamBufferHandle_t uart_stream_buffer;
static uint8_t uart_dma_rx_buf[UART_DMA_BUF_SIZE];
static uart_dma_buf_t uart_dma_tx_buf[UART_DMA_TX_BUF_NUM];
static uint8_t uart_dma_tx_write;
static uint8_t uart_dma_tx_read;
static EventGroupHandle_t uart_dma_flag;

static void uart_rx_cb(uint8_t* buf, uint32_t len){
	BaseType_t xHigherPriorityTaskWoken = pdFALSE;
	int rlen = xStreamBufferSendFromISR(uart_stream_buffer, buf, len, &xHigherPriorityTaskWoken);
	if(rlen != len){
//			LOG_E("rlen=%d, len=%d!", rlen, len);
	}
	portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
	simpleProtocol_Notify(PROTOCOL_UART_BIT);
}

int uart_init(void)
{
	uart_dma_flag = xEventGroupCreate();
	uart_stream_buffer = xStreamBufferCreate(2048, 1);
	if(!uart_stream_buffer){
		LOG_E("no memory!");
		return -1;
	}
	xEventGroupSetBits(uart_dma_flag, 0x03);
	BSP_Uart_DMA_ReceiveInit(2, uart_dma_rx_buf, sizeof(uart_dma_rx_buf), uart_rx_cb);

	return 0;
}

static uint8_t uart_dma_buf_used(void){
	uint8_t used_count = uart_dma_tx_write - uart_dma_tx_read;
	return used_count;
}

static void uart_tx_cb(uint8_t index);

static void uart_dma_send(uint8_t index){
	uart_dma_buf_t* buf = &uart_dma_tx_buf[index&1];
	BSP_Uart_DMA_Send(2, buf->buf, buf->len, index, uart_tx_cb);
}

static void uart_tx_cb(uint8_t index){
	uart_dma_tx_read = index + 1;
	uint8_t b = UART_DMA_F_FREE; //有空余空间
	BaseType_t xHigherPriorityTaskWoken = pdFALSE;
	uint8_t used_count = uart_dma_buf_used();
	if(used_count > 0){
		//仍有数据要发送
		uart_dma_send(uart_dma_tx_read);
	}
	else{
		//没有数据要发送
		b |= UART_DMA_F_IDLE;
	}
	xEventGroupSetBitsFromISR(uart_dma_flag, b, &xHigherPriorityTaskWoken);
	portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}

static uint16_t uart_dma_buf_write(uint8_t index, const uint8_t * data, uint16_t len){
	uint16_t wlen;
	uart_dma_buf_t* tx_buf = &uart_dma_tx_buf[index&1];
	if(len > sizeof(tx_buf->buf)){
		wlen = sizeof(tx_buf->buf);
	}
	else{
		wlen = len;
	}
	tx_buf->len = wlen;
	memcpy(tx_buf->buf, data, tx_buf->len);
	return wlen;
}

static uint16_t uart_dma_write(const uint8_t* data, uint16_t len){
	uint16_t off = 0;
	uint16_t tx_len;

	while(off < len){
		uint8_t used_count = uart_dma_buf_used();
		if(used_count < UART_DMA_TX_BUF_NUM){
			uint8_t index = uart_dma_tx_write++;
			tx_len = uart_dma_buf_write(index, data + off, len - off);
			off += tx_len;
		}
		else{
			break;
		}
	}
	
	return off;
}


//USART
void uart_send(const uint8_t *data, uint16_t len)
{
	uint16_t tx_len;
	uint16_t off = 0;
	EventBits_t b;
	
	while(off < len){
		tx_len = uart_dma_write(data + off, len - off);
		if(tx_len > 0){
			off += tx_len;
		}
		//判断是否空闲
		b = xEventGroupWaitBits(uart_dma_flag, UART_DMA_F_IDLE, pdTRUE, pdFALSE, 0);
		if(b & UART_DMA_F_IDLE){
			//当前空闲，启动发送
			uart_dma_send(uart_dma_tx_read);
		}
		
		if(off < len){
			//仍有数据要发送，等待有空余空间
			b = xEventGroupWaitBits(uart_dma_flag, UART_DMA_F_FREE, pdTRUE, pdFALSE, 100);
			if(!b){
				LOG_E("send time out!!");
				break;
			}
		}
	}
}



int uart_get_byte(int wtime){
	uint8_t rx;
	
	if(xStreamBufferReceive(uart_stream_buffer, &rx, sizeof(rx), wtime) > 0){
		return rx;
	}
	
	return -1;
}

int uart_check_rx(void){
	return pdFALSE == xStreamBufferIsEmpty(uart_stream_buffer);
}

void uart_clear_rx(void){
	xStreamBufferReset(uart_stream_buffer);
}

